package com.ruoyi.monitorTools.task;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.constant.WebSocketConstant;
import com.ruoyi.ky450.service.WebSocketServer;
import com.ruoyi.ky450.vo.WebSocketVo;
import com.ruoyi.monitorTools.domain.*;
import com.ruoyi.monitorTools.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Author wsl
 * @Date 2025-02-13 9:31
 * @Version 1.0
 */

@Configuration
@EnableScheduling
@Slf4j
public class RegularlyModifyEnableStatusTasks  implements SchedulingConfigurer {

    @Autowired
    private ElectronicFenceService electronicFenceService;

    @Autowired
    private RecordReadingLocationService recordReadingLocationService;


    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private A2ROfEFIntrusionService a2ROfEFIntrusionService;

    @Autowired
    private AisDynamicInfoService aisDynamicInfoService;

    @Autowired
    private AdsbDynamicInfoService adsbDynamicInfoService;

    @Autowired
    private HotSpotRegionService hotSpotRegionService;


    @Autowired
    private WebSocketServer webSocketServer;

    @Autowired
    private HotTripNumberService hotTripNumberService;

    private static final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap(1024);

    //记录区域内当前有多少目标
    public static final ConcurrentHashMap<Long, HashSet<String>> targetNum = new ConcurrentHashMap<>();

    private static final String ADS = "ADS-";

    private static final String AIS = "AIS-";




    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                () -> this.execute(),
                triggerContext -> {
                    //每日零点执行
                    String cron = "0 0 0 * * ?";
//                    String cron = "0/5 * * * * ?";
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );

//        taskRegistrar.addTriggerTask(
//                () -> this.selectDynamicInfo(),
//                triggerContext -> {
//                    //每日零点执行
//                    String cron = "0/5 * * * * ?";
//                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
//                }
//        );
    }

    /**
     * @description:  根据电子围栏的结束时间   自动更改电子围栏的状态   判断已结束时间在当前时间之前 修改为禁止
     * @author: wsl
     * @date: 2025-02-13 13:30
     **/
    public void execute() {
        QueryWrapper<ElectronicFence> wrapper = new QueryWrapper<>();
        wrapper.select("task_id", "enable_status", "end_time");
        wrapper.eq("enable_status", 1);
        List<ElectronicFence> list = electronicFenceService.list(wrapper);
        Date now = new Date();
        list.parallelStream().forEach(electronicFence -> {
            if(electronicFence.getEndTime().before(now)){
                electronicFenceService.updateEnableStatusById(electronicFence.getTaskId(), 2);
            }
        });
    }

    public void selectDynamicInfo(){

        System.out.println("---------------------------------------------------------------------------------");
        RecordReadingLocation localtion = recordReadingLocationService.getOne(null);
        //数据库为空时 补全数据
        if(localtion == null){
            localtion = new RecordReadingLocation();
            localtion.setId(1L);
            localtion.setAdsbDynamicInfo(0L);
            localtion.setAisDynamicInfo(0L);
        }
        //查询出飞机盒舰船需要处理的点位， 合并进行处理
        //获取当前最大创建时间
        Long maxAisDate = aisDynamicInfoService.selectMaxCreatetime();
        // 查询出需要判断的数据
        QueryWrapper<DynamicInfo> aisQueryWrapper = new QueryWrapper<>();
        aisQueryWrapper.select("id", "mmsi as code", "base_time", "lon", "lat", "speed", "way", "type as 2");
        aisQueryWrapper.between("create_time", localtion.getAisDynamicInfo(), maxAisDate);
        List<DynamicInfo> aisList = aisDynamicInfoService.list(aisQueryWrapper);

        //获取当前最大创建时间
        Long maxAdsbDate = adsbDynamicInfoService.selectMaxCreatetime();
        // 查询出需要判断的数据
        QueryWrapper<DynamicInfo> adsbQueryWrapper = new QueryWrapper<>();
        adsbQueryWrapper.select("id", "icao as code", "base_time", "lon", "lat", "speed", "way", "type as 1");
        adsbQueryWrapper.between("create_time", localtion.getAdsbDynamicInfo(), maxAdsbDate);
        List<DynamicInfo> adsbList = adsbDynamicInfoService.list(adsbQueryWrapper);
        aisList.addAll(adsbList);

        Map<String, List<DynamicInfo>> adsMap = aisList.stream()
                .collect(Collectors.groupingBy(
                        DynamicInfo::getCode,
                        Collectors.mapping(
                                Function.identity(),
                                Collectors.collectingAndThen(
                                        Collectors.toList(),
                                        list -> {
                                            list.sort(Comparator.comparing(DynamicInfo::getBaseTime));
                                            return list;
                                        }
                                )
                        )
                ));

        //把每条航线得点交给线程池去执行
        adsMap.forEach((k, v) -> {
            threadPoolTaskExecutor.execute(() ->{
                //1. 判断点位的状态  在几个区域内
                for (DynamicInfo adsbDynamicInfo : v) {
//                    try {
//                        Thread.sleep(1000);
//                    } catch (InterruptedException e) {
//                        throw new RuntimeException(e);
//                    }
                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo(WebSocketConstant.REAL_TIME_TRAJECTORY,adsbDynamicInfo)));
                    Set<String> keySet = map.keySet().stream().filter(key -> key.startsWith(ADS + adsbDynamicInfo.getCode())).collect(Collectors.toSet());
                    //判断是否在区域内
                    List<ElectronicFence> eleList = electronicFenceService.isBreakOrOut(adsbDynamicInfo.getLon(), adsbDynamicInfo.getLat(), adsbDynamicInfo.getBaseTime());
                    calculateEle(eleList, keySet, adsbDynamicInfo);

                    List<HotSpotRegion> hotList = hotSpotRegionService.isBreakOrOut(adsbDynamicInfo.getLon(), adsbDynamicInfo.getLat(), adsbDynamicInfo.getBaseTime());
                    calculateHot(hotList, keySet, adsbDynamicInfo);

                }
            });
        });


        UpdateWrapper<RecordReadingLocation> wrap = new UpdateWrapper<>();
        wrap.eq("id", localtion.getId());
        wrap.set("adsb_dynamic_info", maxAdsbDate);
        wrap.set("ais_dynamic_info", maxAisDate);
        recordReadingLocationService.update(wrap);
    }

    //计算 电子围栏闯入闯出
    public void calculateEle(List<ElectronicFence> breakOrOut, Set<String> keySet, DynamicInfo adsbDynamicInfo){
        if(CollectionUtils.isNotEmpty(breakOrOut)){
            //2. 根据上一个点的状态，判断是不是闯入闯出 然后插入记录数据 更新闯入闯出状态
            Set<String> cacheSet = new HashSet<>();
            for (ElectronicFence electronicFence : breakOrOut) {
                String key = ADS + adsbDynamicInfo.getCode() + "-" + electronicFence.getTaskId();
                if(map.get(key) == null ||  map.get(key) != 1){
                    //todo 电子围栏闯入
                    A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
                    a2ROfEFIntrusion.setTask_id(electronicFence.getTaskId());
                    a2ROfEFIntrusion.setPoint_id(adsbDynamicInfo.getId());
                    a2ROfEFIntrusion.setBehavior(1);
                    a2ROfEFIntrusionService.save(a2ROfEFIntrusion);

                    HashMap<String, Object> websocketMap = new HashMap<>();
                    websocketMap.put("lon", adsbDynamicInfo.getLon());
                    websocketMap.put("lat", adsbDynamicInfo.getLat());
                    websocketMap.put("mmsiIcao", adsbDynamicInfo.getCode());
                    websocketMap.put("behavior", 1);
                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("ELE", websocketMap)));
                    map.put(key, 1);
                }
                cacheSet.add(key);
            }
            //3. 查询之前存在但是现在不在的区域  修改为闯出
            keySet.removeAll(cacheSet);

            if(CollectionUtils.isNotEmpty(keySet)){
                //todo 闯出
                keySet.forEach(key ->{
                    if(map.get(key) != null  && map.get(key) == 1){
                        A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
                        String taskId = key.substring(key.lastIndexOf("-") + 1, key.length());
                        a2ROfEFIntrusion.setTask_id(Long.valueOf(taskId));
                        a2ROfEFIntrusion.setPoint_id(adsbDynamicInfo.getId());
                        a2ROfEFIntrusion.setBehavior(2);
                        a2ROfEFIntrusionService.save(a2ROfEFIntrusion);
                        map.put(key, 2);
//                                    StaticInfo a2StaticInfo = staticInfoService.selectByMmsiIcao(adsbDynamicInfo.getMmsiIcao());
                        HashMap<String, Object> websocketMap = new HashMap<>();
//                                    websocketMap.put("name", a2StaticInfo.getName());
                        websocketMap.put("lon", adsbDynamicInfo.getLon());
                        websocketMap.put("lat", adsbDynamicInfo.getLat());
                        websocketMap.put("mmsiIcao", adsbDynamicInfo.getCode());
                        websocketMap.put("behavior", 2);

                        webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("ELE", websocketMap)));
                    }
                });
            }
        } else {
            //3. 查询之前存在但是现在不在的区域  修改为闯出
            if(CollectionUtils.isNotEmpty(keySet)){
                keySet.forEach(key -> {
                    //闯出
                    if(map.get(key) != null  && map.get(key) == 1){
                        A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
                        String taskId = key.substring(key.lastIndexOf("-") + 1, key.length());
                        a2ROfEFIntrusion.setTask_id(Long.valueOf(taskId));
                        a2ROfEFIntrusion.setPoint_id(adsbDynamicInfo.getId());
                        a2ROfEFIntrusion.setBehavior(2);
                        a2ROfEFIntrusionService.save(a2ROfEFIntrusion);

                        HashMap<String, Object> websocketMap = new HashMap<>();
                        websocketMap.put("lon", adsbDynamicInfo.getLon());
                        websocketMap.put("lat", adsbDynamicInfo.getLat());
                        websocketMap.put("mmsiIcao", adsbDynamicInfo.getCode());
                        websocketMap.put("behavior", 2);

                        webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("ELE", websocketMap)));
                        map.put(key, 2);
                    }
                });
            }
        }
    }

    public void calculateHot(List<HotSpotRegion> breakOrOut, Set<String> keySet, DynamicInfo adsbDynamicInfo ){
        if(CollectionUtils.isNotEmpty(breakOrOut)){
            //2. 根据上一个点的状态，判断是不是闯入闯出 然后插入记录数据 更新闯入闯出状态
            Set<String> cacheSet = new HashSet<>();
            for (HotSpotRegion hotSpotRegion : breakOrOut) {
                String key = ADS + adsbDynamicInfo.getCode() + "-" + hotSpotRegion.getTaskId();
                if(map.get(key) == null ||  map.get(key) != 1){

                    HotTripNumber hotTripNumber = new HotTripNumber();
                    hotTripNumber.setTaskId(hotSpotRegion.getTaskId());
                    hotTripNumber.setPointId(adsbDynamicInfo.getId());
                    hotTripNumber.setMmsiIcao(adsbDynamicInfo.getCode());
                    hotTripNumber.setBehavior(1);
                    hotTripNumberService.save(hotTripNumber);
                    targetNum.computeIfAbsent(hotSpotRegion.getTaskId(), value -> new HashSet<>()).add(adsbDynamicInfo.getCode());
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("taskId", hotSpotRegion.getTaskId());
                    resultMap.put("size", targetNum.get(hotSpotRegion.getTaskId()).size());
                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("HOT", resultMap)));
                    map.put(key, 1);
                }
                cacheSet.add(key);
            }
            //3. 查询之前存在但是现在不在的区域  修改为闯出
            keySet.removeAll(cacheSet);

            if(CollectionUtils.isNotEmpty(keySet)){
                //todo 闯出
                keySet.forEach(key ->{
                    if(map.get(key) != null  && map.get(key) == 1){
                        HotTripNumber hotTripNumber = new HotTripNumber();
                        String taskID = key.substring(key.lastIndexOf("-") + 1, key.length());
                        hotTripNumber.setTaskId(Long.valueOf(taskID));
                        hotTripNumber.setPointId(adsbDynamicInfo.getId());
                        hotTripNumber.setMmsiIcao(adsbDynamicInfo.getCode());
                        hotTripNumber.setBehavior(2);
                        hotTripNumberService.save(hotTripNumber);
                        targetNum.getOrDefault(Long.valueOf(taskID), new HashSet<>()).remove(adsbDynamicInfo.getCode());
                        Map<String, Object> resultMap = new HashMap<>();
                        resultMap.put("taskId", taskID);
                        resultMap.put("size", targetNum.get(Long.valueOf(taskID)).size());
                        webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("HOT", resultMap)));
                        map.put(key, 2);
                    }
                });
            }
        } else {
            //3. 查询之前存在但是现在不在的区域  修改为闯出
            if(CollectionUtils.isNotEmpty(keySet)){
                keySet.forEach(key -> {
                    //闯出
                    if(map.get(key) != null  && map.get(key) == 1){

                        HotTripNumber hotTripNumber = new HotTripNumber();
                        String taskID = key.substring(key.lastIndexOf("-") + 1, key.length());
                        hotTripNumber.setTaskId(Long.valueOf(taskID));
                        hotTripNumber.setPointId(adsbDynamicInfo.getId());
                        hotTripNumber.setMmsiIcao(adsbDynamicInfo.getCode());
                        hotTripNumber.setBehavior(2);
                        hotTripNumberService.save(hotTripNumber);
                        targetNum.getOrDefault(Long.valueOf(taskID), new HashSet<>()).remove(adsbDynamicInfo.getCode());
                        Map<String, Object> resultMap = new HashMap<>();
                        resultMap.put("taskId", taskID);
                        resultMap.put("size", targetNum.get(Long.valueOf(taskID)).size());
                        webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("HOT", resultMap)));
                        map.put(key, 2);
                    }
                });
            }
        }
    }


}
